#ifndef _MUNIX_COMMON_H_
#define _MUNIX_COMMON_H_
/*******************************************************************************
 **  Name: common.h                                                           **
 **  Description:                                                             **
 **                                                                           **
 **  CDDL: Open Source Initiative (OSI) Approved License                      **
 **                                                                           **
 **  Copyright (c) 2009-2010 Barry "Gian" James  <bjames@munixos.net>         **
 **  All rights reserved.                                                     **
 **                                                                           **
 **  The contents of this file are subject to the terms of the CDDL:          **
 **  Common Development and Distribution License (the "License").             **
 **  You may not use this file except in compliance with the License.         **
 **                                                                           **
 **  You can obtain a copy of the license at $PROJECT_ROOT/LICENSE            **
 **  or http://www.opensolaris.org/os/licensing.  This code is Open Source    **
 **  and you are free to use it within the confines of the license, even      **
 **  for your own closed-source commercial projects, as long as you follow    **
 **  the terms set forth in the CDDL.                                         **
 **                                                                           **
 **  When distributing Covered Code, include this CDDL HEADER in each         **
 **  file and include the License file at $PROJECT_ROOT/LICENSE.              **
 **  If applicable, add the following below this CDDL HEADER, with the        **
 **  fields enclosed by brackets "[]" replaced with your own identifying      **
 **  information: Portions Copyright [yyyy] [name of copyright owner]         **
 **                                                                           **
 ******************************************************************************/
// Modified $DateTime$ by $Author$
#define _MUNIX_COMMON_ID    "$Id$"

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

// Typedefs for shorthand
// I wonder how much time programmers around the world have lost from having
// to type "_t"...lolz
typedef uint8_t		uint8;
typedef int8_t      int8;
typedef uint16_t	uint16;
typedef uint32_t	uint32;
typedef unsigned char uchar;
typedef wchar_t     wchar;

enum class BusMode { Master, Slave };

#if defined(__AVR__)
#include <avr/io.h>
typedef unsigned long   time_t;

// If you don't set F_CPU in your application, it defaults to 20MHz
#ifndef F_CPU
#define F_CPU 20000000
#endif

// C++ Sanity Wrappers
#define nop()                       (asm volatile("nop\n\t"::))
#define BEGIN_CRITICAL_SECTION    (asm volatile("ldi r16, SREG\n\tcli\n\t"::))
#define END_CRITICAL_SECTION      (asm volatile("out SREG, r16\n\tsei\n\t"::))
//#define BEGIN_CRITICAL_SECTION()    (volatile uint8 __sregSave = SREG, cli())
//#define END_CRITICAL_SECTION()      (SREG = __sregSave, sei())
#endif  /* __AVR */

#if defined(_WIN32)
#define FNAME()                     __FUNCSIG__
#else
#define FNAME()						__PRETTY_FUNCTION__
#endif

// This just makes my life easier
//#define BIT16(b) ((unsigned long)0x00000001 << (b))
#define BIT32(b) ((uint32)0x00000001 << (b))
#define BIT16(b) ((uint16)0x0001 << (b))
#define	BIT8(b) (0x01 << (b))

// from AVR035: Efficient C Coding for AVR
#define BSET(ADDRESS,BIT) (ADDRESS |= (unsigned char)(1<<BIT))
#define BCLR(ADDRESS,BIT) (ADDRESS &= (unsigned char)~(1<<BIT))
#define BTOG(ADDRESS,BIT) (ADDRESS ^= (unsigned char)(1<<BIT))
#define BCHK(ADDRESS,BIT) (ADDRESS &  (unsigned char)(1<<BIT))

#define BMSET(x,y) (x |= (y))
#define BMCLR(x,y) (x &= (~y))
#define BMTOG(x,y) (x ^= (y))
#define BMCHK(x,y) (x & (y))

#ifndef Max
#define Max(x,y) ((x)>=(y)?(x):(y))
#endif

#ifndef Min
#define Min(x,y) ((x)<=(y)?(x):(y))
#endif

#ifndef Abs
#define Abs(x) ((x) < 0 ? -(x) : (x))
#endif

#ifndef PI
#define PI 3.1415927
#endif

enum class Signal { Low, High };

enum class Direction : uint8 { North, NorthEast, East, SouthEast, South, SouthWest, West, NorthWest };


#if defined(__AVR)
//////////////////////// [ C++ Safety functions
__extension__ typedef int __guard __attribute__ ((mode (__DI__)));
#ifdef __cplusplus
extern "C" {
#endif
void __cxa_pure_virtual(void);
#if !defined(NO_THREADSAFE_STATICS)
int  __cxa_guard_acquire(__guard *);
void __cxa_guard_release(__guard *);
void __cxa_guard_abort(__guard*);
#endif  /* !NO_THREADSAFE_STATICS */
#ifdef __cplusplus
}
#endif


#if defined(DEFINE_ATEXIT)
void atexit(void) { }	// firmware never exits...
#endif

#if !defined(USE_MEM_MGMT)
// These should be moved into the memory management section when it gets written
void * operator new(size_t size);		// new replacement
void * operator new(size_t, void*);		// placement new
void * operator new[] (size_t size);
void operator delete(void * ptr);
void operator delete(void * p, void * const b);	// placement delete..hmmm
void operator delete[] (void * ptr);
#endif

// Power definitions as found in <avr/power.h>
#if defined (__AVR_ATmega324P__) || defined(__AVR_ATmega644P__)
#define power_spi_enable()      (PRR0 &= (uint8_t)~(1 << PRSPI))
#define power_spi_disable()     (PRR0 |= (uint8_t)(1 << PRSPI))

#define power_usart0_enable()   (PRR0 &= (uint8_t)~(1 << PRUSART0))
#define power_usart0_disable()  (PRR0 |= (uint8_t)(1 << PRUSART0))
#define power_usart1_enable()   (PRR0 &= (uint8_t)~(1 << PRUSART1))
#define power_usart1_disable()  (PRR0 |= (uint8_t)(1 << PRUSART1))

#define power_timer0_enable()   (PRR0 &= (uint8_t)~(1 << PRTIM0))
#define power_timer0_disable()  (PRR0 |= (uint8_t)(1 << PRTIM0))
#define power_timer1_enable()   (PRR0 &= (uint8_t)~(1 << PRTIM1))
#define power_timer1_disable()  (PRR0 |= (uint8_t)(1 << PRTIM1))
#define power_timer2_enable()   (PRR0 &= (uint8_t)~(1 << PRTIM2))
#define power_timer2_disable()  (PRR0 |= (uint8_t)(1 << PRTIM2))

#define power_twi_enable()      (PRR0 &= (uint8_t)~(1 << PRTWI))
#define power_twi_disable()     (PRR0 |= (uint8_t)(1 << PRTWI))

// #elif defined(__AVR_ATmega32__)

#elif defined(__AVR_ATmega48__) \
|| defined(__AVR_ATmega48P__) \
|| defined(__AVR_ATmega88__) \
|| defined(__AVR_ATmega88P__) \
|| defined(__AVR_ATmega168__) \
|| defined(__AVR_ATmega168P__) \
|| defined(__AVR_ATmega328P__) \
|| defined(__AVR_ATtiny48__) \
|| defined(__AVR_ATtiny88__)

#define power_adc_enable()      (PRR &= (uint8_t)~(1 << PRADC))
#define power_adc_disable()     (PRR |= (uint8_t)(1 << PRADC))

#define power_spi_enable()      (PRR &= (uint8_t)~(1 << PRSPI))
#define power_spi_disable()     (PRR |= (uint8_t)(1 << PRSPI))

#define power_usart0_enable()   (PRR &= (uint8_t)~(1 << PRUSART0))
#define power_usart0_disable()  (PRR |= (uint8_t)(1 << PRUSART0))

#define power_timer0_enable()   (PRR &= (uint8_t)~(1 << PRTIM0))
#define power_timer0_disable()  (PRR |= (uint8_t)(1 << PRTIM0))
#define power_timer1_enable()   (PRR &= (uint8_t)~(1 << PRTIM1))
#define power_timer1_disable()  (PRR |= (uint8_t)(1 << PRTIM1))
#define power_timer2_enable()   (PRR &= (uint8_t)~(1 << PRTIM2))
#define power_timer2_disable()  (PRR |= (uint8_t)(1 << PRTIM2))

#define power_twi_enable()      (PRR &= (uint8_t)~(1 << PRTWI))
#define power_twi_disable()     (PRR |= (uint8_t)(1 << PRTWI))

#elif defined(__AVR_ATtiny24__) \
|| defined(__AVR_ATtiny44__) \
|| defined(__AVR_ATtiny84__) \
|| defined(__AVR_ATtiny25__) \
|| defined(__AVR_ATtiny45__) \
|| defined(__AVR_ATtiny85__) \
|| defined(__AVR_ATtiny261__) \
|| defined(__AVR_ATtiny461__) \
|| defined(__AVR_ATtiny861__) \
|| defined(__AVR_ATtiny43U__)

#define power_adc_enable()      (PRR &= (uint8_t)~(1 << PRADC))
#define power_adc_disable()     (PRR |= (uint8_t)(1 << PRADC))

#define power_timer0_enable()   (PRR &= (uint8_t)~(1 << PRTIM0))
#define power_timer0_disable()  (PRR |= (uint8_t)(1 << PRTIM0))
#define power_timer1_enable()   (PRR &= (uint8_t)~(1 << PRTIM1))
#define power_timer1_disable()  (PRR |= (uint8_t)(1 << PRTIM1))

/* Universal Serial Interface */
#define power_usi_enable()      (PRR &= (uint8_t)~(1 << PRUSI))
#define power_usi_disable()     (PRR |= (uint8_t)(1 << PRUSI))

#elif defined(__AVR_ATxmega64A3__) || defined(__AVR_ATxmega128A3__) \
    || defined(__AVR_ATxmega256A3__) || defined(__AVR_ATxmega32A4__)

#define power_ebi_enable()  (PR_PR &= (uint8_t)~(PR_EBI_bm))
#define power_ebi_disable() (PR_PR |= (uint8_t)PR_EBI_bm)

#define power_rtc_enable()  (PR_PR &= (uint8_t)~(PR_RTC_bm))
#define power_rtc_disable() (PR_PR |= (uint8_t)PR_RTC_bm)

#define power_evsys_enable()    (PR_PR &= (uint8_t)~(PR_EVSYS_bm))
#define power_evsys_disable()   (PR_PR |= (uint8_t)PR_EVSYS_bm)

#define power_dma_enable()    (PR_PR &= (uint8_t)~(PR_DMA_bm))
#define power_dma_disable()   (PR_PR |= (uint8_t)PR_DMA_bm)

#define power_daca_enable()     (PR_PRPA &= (uint8_t)~(PR_DAC_bm))
#define power_daca_disable()    (PR_PRPA |= (uint8_t)PR_DAC_bm)
#define power_dacb_enable()     (PR_PRPB &= (uint8_t)~(PR_DAC_bm))
#define power_dacb_disable()    (PR_PRPB |= (uint8_t)PR_DAC_bm)

#define power_adca_enable()     (PR_PRPA &= (uint8_t)~(PR_ADC_bm))
#define power_adca_disable()    (PR_PRPA |= (uint8_t)PR_ADC_bm)
#define power_adcb_enable()     (PR_PRPB &= (uint8_t)~(PR_ADC_bm))
#define power_adcb_disable()    (PR_PRPB |= (uint8_t)PR_ADC_bm)

#define power_aca_enable()      (PR_PRPA &= (uint8_t)~(PR_AC_bm))
#define power_aca_disable()     (PR_PRPA |= (uint8_t)PR_AC_bm)
#define power_acb_enable()      (PR_PRPB &= (uint8_t)~(PR_AC_bm))
#define power_acb_disable()     (PR_PRPB |= (uint8_t)PR_AC_bm)

#define power_twic_enable()     (PR_PRPC &= (uint8_t)~(PR_TWI_bm))
#define power_twic_disable()    (PR_PRPC |= (uint8_t)PR_TWI_bm)
#define power_twid_enable()     (PR_PRPD &= (uint8_t)~(PR_TWI_bm))
#define power_twid_disable()    (PR_PRPD |= (uint8_t)PR_TWI_bm)
#define power_twie_enable()     (PR_PRPE &= (uint8_t)~(PR_TWI_bm))
#define power_twie_disable()    (PR_PRPE |= (uint8_t)PR_TWI_bm)
#define power_twif_enable()     (PR_PRPF &= (uint8_t)~(PR_TWI_bm))
#define power_twif_disable()    (PR_PRPF |= (uint8_t)PR_TWI_bm)

#define power_usartc1_enable()  (PR_PRPC &= (uint8_t)~(PR_USART1_bm))
#define power_usartc1_disable() (PR_PRPC |= (uint8_t)PR_USART1_bm)
#define power_usartd1_enable()  (PR_PRPD &= (uint8_t)~(PR_USART1_bm))
#define power_usartd1_disable() (PR_PRPD |= (uint8_t)PR_USART1_bm)
#define power_usarte1_enable()  (PR_PRPE &= (uint8_t)~(PR_USART1_bm))
#define power_usarte1_disable() (PR_PRPE |= (uint8_t)PR_USART1_bm)
#define power_usartf1_enable()  (PR_PRPF &= (uint8_t)~(PR_USART1_bm))
#define power_usartf1_disable() (PR_PRPF |= (uint8_t)PR_USART1_bm)

#define power_usartc0_enable()  (PR_PRPC &= (uint8_t)~(PR_USART0_bm))
#define power_usartc0_disable() (PR_PRPC |= (uint8_t)PR_USART0_bm)
#define power_usartd0_enable()  (PR_PRPD &= (uint8_t)~(PR_USART0_bm))
#define power_usartd0_disable() (PR_PRPD |= (uint8_t)PR_USART0_bm)
#define power_usarte0_enable()  (PR_PRPE &= (uint8_t)~(PR_USART0_bm))
#define power_usarte0_disable() (PR_PRPE |= (uint8_t)PR_USART0_bm)
#define power_usartf0_enable()  (PR_PRPF &= (uint8_t)~(PR_USART0_bm))
#define power_usartf0_disable() (PR_PRPF |= (uint8_t)PR_USART0_bm)

#define power_spic_enable()     (PR_PRPC &= (uint8_t)~(PR_SPI_bm))
#define power_spic_disable()    (PR_PRPC |= (uint8_t)PR_SPI_bm)
#define power_spid_enable()     (PR_PRPD &= (uint8_t)~(PR_SPI_bm))
#define power_spid_disable()    (PR_PRPD |= (uint8_t)PR_SPI_bm)
#define power_spie_enable()     (PR_PRPE &= (uint8_t)~(PR_SPI_bm))
#define power_spie_disable()    (PR_PRPE |= (uint8_t)PR_SPI_bm)
#define power_spif_enable()     (PR_PRPF &= (uint8_t)~(PR_SPI_bm))
#define power_spif_disable()    (PR_PRPF |= (uint8_t)PR_SPI_bm)

#define power_hiresc_enable()   (PR_PRPC &= (uint8_t)~(PR_HIRES_bm))
#define power_hiresc_disable()  (PR_PRPC |= (uint8_t)PR_HIRES_bm)
#define power_hiresd_enable()   (PR_PRPD &= (uint8_t)~(PR_HIRES_bm))
#define power_hiresd_disable()  (PR_PRPD |= (uint8_t)PR_HIRES_bm)
#define power_hirese_enable()   (PR_PRPE &= (uint8_t)~(PR_HIRES_bm))
#define power_hirese_disable()  (PR_PRPE |= (uint8_t)PR_HIRES_bm)
#define power_hiresf_enable()   (PR_PRPF &= (uint8_t)~(PR_HIRES_bm))
#define power_hiresf_disable()  (PR_PRPF |= (uint8_t)PR_HIRES_bm)

#define power_tc1c_enable()     (PR_PRPC &= (uint8_t)~(PR_TC1_bm))
#define power_tc1c_disable()    (PR_PRPC |= (uint8_t)PR_TC1_bm)
#define power_tc1d_enable()     (PR_PRPD &= (uint8_t)~(PR_TC1_bm))
#define power_tc1d_disable()    (PR_PRPD |= (uint8_t)PR_TC1_bm)
#define power_tc1e_enable()     (PR_PRPE &= (uint8_t)~(PR_TC1_bm))
#define power_tc1e_disable()    (PR_PRPE |= (uint8_t)PR_TC1_bm)
#define power_tc1f_enable()     (PR_PRPF &= (uint8_t)~(PR_TC1_bm))
#define power_tc1f_disable()    (PR_PRPF |= (uint8_t)PR_TC1_bm)

#define power_tc0c_enable()     (PR_PRPC &= (uint8_t)~(PR_TC0_bm))
#define power_tc0c_disable()    (PR_PRPC |= (uint8_t)PR_TC0_bm)
#define power_tc0d_enable()     (PR_PRPD &= (uint8_t)~(PR_TC0_bm))
#define power_tc0d_disable()    (PR_PRPD |= (uint8_t)PR_TC0_bm)
#define power_tc0e_enable()     (PR_PRPE &= (uint8_t)~(PR_TC0_bm))
#define power_tc0e_disable()    (PR_PRPE |= (uint8_t)PR_TC0_bm)
#define power_tc0f_enable()     (PR_PRPF &= (uint8_t)~(PR_TC0_bm))
#define power_tc0f_disable()    (PR_PRPF |= (uint8_t)PR_TC0_bm)

//#elif defined(__AVR_ATmega2313__)

#endif

//.....................[ <avr/progmem.h>
// Broken progmem in C++. This is a literal cut/paste from <avr/progmem.h>
// This removes the complaint about not setting FCPU and MCU as well as the
// unending and annoying c++ program space errors.
#ifndef __ATTR_CONST__
#define __ATTR_CONST__ __attribute__((__const__))
#endif

#ifndef __ATTR_PROGMEM__
#define __ATTR_PROGMEM__ __attribute__((__progmem__))
#endif

#ifndef __ATTR_PURE__
#define __ATTR_PURE__ __attribute__((__pure__))
#endif

#define PROGMEM __ATTR_PROGMEM__
typedef char PROGMEM prog_char;
# define PSTR(s) (__extension__({static char __c[] PROGMEM = (s); &__c[0];}))

#define __LPM_classic__(addr)   \
(__extension__({                \
    uint16_t __addr16 = (uint16_t)(addr); \
    uint8_t __result;           \
    __asm__                     \
    (                           \
        "lpm" "\n\t"            \
        "mov %0, r0" "\n\t"     \
        : "=r" (__result)       \
        : "z" (__addr16)        \
        : "r0"                  \
    );                          \
    __result;                   \
}))
#define __LPM(addr)         __LPM_classic__(addr)
#define pgm_read_byte_near(address_short) __LPM((uint16_t)(address_short))
#define pgm_read_byte(address_short)    pgm_read_byte_near(address_short)


#define XMEGA_DEFINED   (defined(__AVR_ATxmega64A3__) || defined(__AVR_ATxmega128A3__) \
    || defined(__AVR_ATxmega256A3__) || defined(__AVR_ATxmega32A4__))

#define DUAL_USART	(defined(__AVR_ATmega128__) || defined(__AVR_ATmega644P__) \
	|| defined(__AVR_ATmega1281__) || defined(__AVR_ATmega162__))


#endif	/* defined(__AVR) */

char    Hex2Char(char *);
char *  Char2Hex(char);
char *  StringCopy(const char *);

#endif	/* _MUNIX_COMMON_H_ */
